/*
 * @Date: 2024-06-19 22:50:40
 */

const { sign } = require('crypto');
const FUN = require('./fun');
const Log = require('./log');
const fs = require('fs');
module.exports = class {
    user_env = [];
    Front = require('./Front');
    Database = require('better-sqlite3');
    Db
    constructor() {
        if (!fs.existsSync('./config.json')) {
            fs.writeFileSync('./config.json', JSON.stringify({
                "user_env": [
                    {
                        "username": "",
                        "password": "",
                        "userId": "",
                        "usedelicate": false,
                        "buyFertilizer": false
                    }
                ],
                "push_config": {
                    "PUSHME_KEY": "",
                    "PUSHME_URL": ""
                },
                "log": {
                    "saveTime": 7
                }
            }, null, 2));
        }
        let config = fs.readFileSync('./config.json', 'utf8');
        this.user_env = JSON.parse(config).user_env;
        global.log = new Log(JSON.parse(config).push_config, JSON.parse(config).log);
        this.Db = new this.Database('./config.db');
        if (!checkTableExists(this.Db, "info")) {//新文件
            this.Db.exec(`CREATE TABLE info ( username TEXT PRIMARY KEY, money TEXT DEFAULT '0', activeVal INT DEFAULT 0, sign_num INT DEFAULT 0, sign_total INT DEFAULT 0, field_level INT DEFAULT 0, field_specimen INT DEFAULT 0, animal_level INT DEFAULT 0, animal_specimen INT DEFAULT 0 );`);
        }
        if (!checkTableExists(this.Db, "queue")) {
            this.Db.exec(`CREATE TABLE queue ( username TEXT PRIMARY KEY, field TEXT NULL, animal TEXT NULL, sign_time TEXT NULL, award_time TEXT NULL );`);
        }
        function checkTableExists(db, tableName) {
            const stmt = db.prepare(`SELECT count(*) as count FROM sqlite_master WHERE type='table' AND name = '${tableName}'`);
            const result = stmt.get();
            if (result.count > 0) {
                return true;
            } else {
                return false;
            }
        }
    }

    Loop(run) {
        log.log('开始执行');
        var is_login = true;
        for (let user_env_num = 0; user_env_num < this.user_env.length; user_env_num++) {
            let user = this.user_env[user_env_num];
            if (!user.userId) {//需要进行登录操作
                if (user.password && user.username) {
                    let login = this.Front.post("http://ygmcapi.yiyutx.top/ygmc/login/login", user_data({ account: user.username, password: user.password }), true)
                    if (login != 200) continue;
                    user.userId = login.sessionId;
                    this.user_env[user_env_num] = user;
                }
                is_login = false;
            }
            global.fun = new FUN(user.userId);
            let Db_user = getFromDB(this.Db, "queue", user.username);
            if (!Db_user) {//不存在用户数据
                let field = fun.getHomeData();
                if (!field) {
                    this.user_env[user_env_num].userId = "";
                    continue;
                }
                let animal = fun.getFarmData();
                saveToDB(this.Db, "info", user.username, {
                    money: field.pastureInfoData.money,
                    activeVal: field.activeVal,
                    sign_num: 0,
                    sign_total: 0,
                    field_level: field.pastureInfoData.pasture_level,
                    animal_level: field.pastureInfoData.livestock_level,
                    field_specimen: field.pastureInfoData.specimen_num,
                    animal_specimen: animal?animal.pastureInfoData.specimen_num:null,
                })
                saveToDB(this.Db, "queue", user.username, {
                    field: getMinPortTime(field.portList),
                    animal: animal?getMinPortTime(animal.portList):null,
                    sign_time: "",
                    award_time: "",
                })
            }
            try {
                run(this.user_env[user_env_num].userId,user_env_num);
            } catch (error) {
                log.failure(this.user_env[user_env_num].userId + ':' + error);
            }
        }
        if (is_login) {//已经全部登录过了,创建模板用户位
            this.user_env.push({
                "password": "",
                "username": "",
                "userId": "",
                "usedelicate": false,
                "buyFertilizer": false
            })
        }
        function getFromDB(db, table, username) {
            let stmt = db.prepare(`SELECT * FROM ${table} WHERE username = '${username}'`).get();
            return stmt ? stmt : false;
        }
        function user_data(param = {}) {
            return { "data": Object.assign({ "version": "2.6.1" }, param), "checkTime": new Date().getTime, "imei": "", "type": 1, "version": "2.6.1" };
        }
        return this;
    }

    exit() {
        //存档文件
        let config = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
        config.user_env = this.user_env;
        fs.writeFileSync('./config.json', JSON.stringify(config, null, 2))
        //保存数据库
        //关闭数据库
        this.Db.close();
    }
}
function saveToDB(db, table, username, param) {
    const existingData = db.prepare(`SELECT * FROM ${table} WHERE username = '${username}'`).get();
    let update = [];
    for (const key in param) {
        update.push(`${key} = '${param[key]}'`);
    }
    if (existingData) {//更新
        return db.prepare(`UPDATE ${table} SET ${update.join(',')} WHERE username = '${username}'`).run();
    } else {//插入
        return db.prepare(`INSERT INTO ${table} (username, ${Object.keys(param).join(',')}) VALUES ('${username}', ${Object.values(param).map(value => `'${value}'`).join(',')})`).run();
    }
}
function getMinPortTime(portList) {
    let minNextTime = Date.parse(new Date()) / 1000;
    for (let port of portList) {
        let timeStr = port.nextTime;
        let day = parseInt(timeStr.match(/(\d+)天/)?.[1] || 0);
        let hours = parseInt(timeStr.match(/(\d+)时/)?.[1] || 0);
        let minutes = parseInt(timeStr.match(/(\d+)分/)?.[1] || 0);
        let seconds = parseInt(timeStr.match(/(\d+)秒/)?.[1] || 0);
        let currentTime = (day * 24 + hours) * 3600 + minutes * 60 + seconds;
        minNextTime = currentTime < minNextTime ? currentTime : minNextTime;
    }
    return minNextTime + Date.parse(new Date()) / 1000
}